
package com.eworking.eim.user;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterStorage;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.RosterPacket;

import com.eworking.eim.EIMChatManager;
import com.eworking.eim.EIMConstants;
import com.eworking.eim.EIMSessionManager;
import com.eworking.eim.exception.EIMException;
import com.eworking.eim.util.EIMLog;
import com.eworking.eim.xmpp.XMPPConnectionManager;

import android.content.Context;
import android.content.Intent;

public class EIMUserManager {
    
    /** 日志标签 */
    private static final String _TAG = EIMUserManager.class.getSimpleName();
    
    private static EIMUserManager userManager = null;
    
    /** 好友集合 key:Account */
    private Map<String, EIMUser> userTable = new Hashtable<String, EIMUser>(100);
    
    private Context context = null;
    
    /** XMPP服务器连接管理 */
    private XMPPConnectionManager xmppConnectionManager = null;
    
    /** 好友名册对象 */
    private Roster roster = null;
    
    /** 用户状态监听 */
    private EIMUserListener userListener = null;
    
    /** 删除的好友账号集合 */
    private Set<String> deletedUserAccount = null;
    
    /** 好友状态监听 */
    private EIMRosterLinstener rosterLinstener = null;
    
    /** 好友数据存储 */
    private RosterStorage rosterStorage = null;
    
    /** 离线好友消息集合 */
    private List<Presence> lstOfflineRosterPresence = new ArrayList<Presence>();
    
    public static EIMUserManager getInstance() {
        if (userManager == null) {
            userManager = new EIMUserManager();
        }
        return userManager;
    }
    
    /**
     * 初始化
     * 
     * @param context
     * @param xmppConnectionManager
     */
    public void init(Context context, XMPPConnectionManager xmppConnectionManager) {
        this.context = context;
        this.xmppConnectionManager = xmppConnectionManager;
        this.rosterStorage = new EIMRosterStorage(context, this);
        // 设置好友信息存储对象
        this.xmppConnectionManager.getConnection().setRosterStorage(this.rosterStorage);
        this.roster = xmppConnectionManager.getConnection().getRoster();
        this.deletedUserAccount = Collections.synchronizedSet(new HashSet<String>());
        this.rosterLinstener = new EIMRosterLinstener(this, this.roster);
        this.roster.addRosterListener(rosterLinstener);
    }
    
    /**
     * 添加好友离线信息
     * 
     * @param presence
     */
    public void addOfflinePresence(Presence presence) {
        this.lstOfflineRosterPresence.add(presence);
    }
    
    /**
     * 获取用户操作监听
     * 
     * @return
     */
    public EIMUserListener getUserListener() {
        return userListener;
    }
    
    /**
     * 设置用户操作监听
     * 
     * @param userListener
     */
    public void setUserListener(EIMUserListener userListener) {
        this.userListener = userListener;
    }
    
    /**
     * 根据用户账号获取用户信息
     * 
     * @param account 用户账号
     * @return 用户信息对象
     */
    public EIMUser getUserByAccount(String account) {
        EIMUser user = (EIMUser) this.userTable.get(account);
        if (user == null) {
            user = new EIMUser(account);
            addUserInternal(user);
        }
        return user;
    }
    
    /**
     * 根据用户账号删除好友
     * 
     * @param account 用户账号
     */
    public void removeUserByAccount(String account) {
        EIMUser user = (EIMUser) this.userTable.remove(account);
        EIMLog.d(_TAG, "removed contact:" + user);
    }
    
    /**
     * 添加好友
     * 
     * @param account 好友账号
     * @param status 状态
     */
    public void addUser(String account, String status) {
        try {
            this.addUserToRosterThroughPresence(account, status);
        } catch (EIMException e) {
            EIMLog.e(_TAG, "添加好友失败：" + e.getMessage());
        }
    }
    
    /**
     * 添加好友
     * 
     * @param eimUser 用户信息对象
     */
    public void addUserFormDB(EIMUser user) {
        this.userTable.put(user.getAccount(), user);
    }
    
    /**
     * 添加好友
     * 
     * @param eimUser 用户信息对象
     */
    public void addUserInternal(EIMUser user) {
        this.userTable.put(user.getAccount(), user);
    }
    
    public Map<String, EIMUser> getUserTable() {
        return userTable;
    }
    
    /**
     * 删除好友
     * 
     * @param account 用户账号
     */
    public void deleteUser(String account) {
        try {
            String JID = EIMAccountUtils.getJIDFromAccount(account);
            RosterEntry rosterEntry = this.roster.getEntry(JID);
            this.roster.removeEntry(rosterEntry);
        } catch (Exception e) {
            EIMLog.e(_TAG, "删除好友失败：" + e.getMessage());
        }
    }
    
    /**
     * 添加好友
     * 
     * @param account 好友账号
     * @param status 状态
     * @throws EIMException
     */
    private void addUserToRosterThroughPresence(String account, String status) throws EIMException {
        try {
            // EIMChatManager.getInstance().checkConnection();
            Presence presence = new Presence(Presence.Type.subscribe);
            // 根据用户账号获取企业账号
            String JID = EIMAccountUtils.getJIDFromAccount(account);
            presence.setTo(JID);
            if ((status != null) && (!("".equals(status)))) {
                presence.setStatus(status);
            }
            // 发送用户状态
            this.xmppConnectionManager.getConnection().sendPacket(presence);
        } catch (Exception localException) {
            throw new EIMException(localException.getMessage());
        }
    }
    
    /**
     * 获取所有好友的昵称
     * 
     * @return List<String> 好友昵称集合
     */
    public List<String> getRosterNickNames() {
        // 获取所有好友
        Collection<RosterEntry> colRosterEntrys = this.roster.getEntries();
        List<String> lstNickNames = new ArrayList<String>(colRosterEntrys.size());
        for (RosterEntry rosterEntry : colRosterEntrys) {
            // both双方已经是好友；from对方已经接受好友请求
            if (rosterEntry.getType() == RosterPacket.ItemType.both
                || rosterEntry.getType() == RosterPacket.ItemType.from) {
                String nickName = rosterEntry.getName();
                if (nickName == null || nickName.equals("")) {
                    // 根据企业账号获取用户账号
                    nickName = EIMAccountUtils.getAccountFromJID(rosterEntry.getUser());
                }
                lstNickNames.add(nickName);
            }
        }
        return lstNickNames;
    }
    
    public void reset() {
        this.userTable.clear();
        this.roster = null;
    }
    
    /**
     * 获取删除的好友账号集合
     * 
     * @return
     */
    public Set<String> getDeletedUserAccount() {
        return deletedUserAccount;
    }
    
    /**
     * 获取当前用户的JID
     * 
     * @return 用户JID
     */
    public String getCurrentUserFullJid() {
        EIMUser user = EIMSessionManager.getInstance(this.context).getCurrentUser();
        String resouce = XMPPConnectionManager.getXMPPResource();
        String JID = EIMAccountUtils.getJIDFromAccount(user.getAccount());
        String userFullJID = JID + "/" + resouce;
        return userFullJID;
    }
    
    /**
     * 接受对方加为好友的邀请
     * 
     * @param account JID JID
     * @param isAccept 是否接受
     */
    public void acceptInvitation(String account, boolean status) {
        try {
            Presence presence = new Presence(Presence.Type.subscribed);
            presence.setMode(Presence.Mode.available);
            presence.setPriority(24);
            presence.setTo(account);
            presence.setStatus("[resp:" + status + "]");
            this.xmppConnectionManager.getConnection().sendPacket(presence);
            if (status) {
                Presence localPresence2 = new Presence(Presence.Type.subscribe);
                localPresence2.setStatus("[resp:true]");
                localPresence2.setTo(account);
                this.xmppConnectionManager.getConnection().sendPacket(presence);
            }
        } catch (Exception e) {
            EIMLog.e(_TAG, "发送接受邀请信息失败：" + e.getMessage());
        }
    }
    
    /**
     * 拒绝加为好友
     * 
     * @param account 用户账号
     */
    public void refuseInvitation(String account) {
        try {
            Presence presence = new Presence(Presence.Type.unsubscribed);
            presence.setTo(EIMAccountUtils.getJIDFromAccount(account));
            this.xmppConnectionManager.getConnection().sendPacket(presence);
        } catch (Exception e) {
            EIMLog.e(_TAG, "发送拒绝邀请信息失败：" + e.getMessage());
        }
    }
    
    /**
     * 好友邀请处理
     * 
     * @param presence
     */
    public void processRosterPresence(Presence presence) {
        String strResp = "[resp:";
        // 好友状态
        String strStatus = presence.getStatus() != null ? presence.getStatus() : null;
        boolean status = false;
        // 添加好友原因
        String reason = "";
        if (strStatus.startsWith(strResp)) {
            // 好友状态
            String strTempStatus = strStatus.substring(strResp.length(), strStatus.indexOf("]"));
            status = Boolean.parseBoolean(strTempStatus);
        }
        // 用户账号
        String account = EIMAccountUtils.getAccountFromJID(presence.getFrom());
        
        // 对方请求添加好友
        if (presence.getType().equals(Presence.Type.subscribe)) {
            if (strStatus.length() > strStatus.indexOf("]") + 1) {
                reason = strStatus.substring(strStatus.indexOf("]" + 1), strStatus.length());
            } else {
                reason = null;
            }
            EIMLog.d(_TAG, "isresp:" + status + " reason:" + reason);
            // 对方设置默认同意所有人添加好友
            if (status) {
                try {
                    // 接受对方添加好友
                    acceptInvitation(presence.getFrom(), false);
                    Intent intent = new Intent(EIMConstants._USER_INVITE_EVENT_BROADCAST);
                    intent.putExtra("account", account);
                    intent.putExtra("isResponse", status);
                    this.context.sendBroadcast(intent);
                    // 执行同意监听方法
                    this.userListener.onUserAgreed(account);
                } catch (Exception exception) {
                    EIMLog.e(_TAG, "接受好友邀请失败： " + exception.getMessage());
                }
            } else {
                // 设置默认同意添加好友，直接回复同意
                if (EIMChatManager.getInstance().getChatOptions().getAcceptInvitationAlways()) {
                    try {
                        // 接受对方添加好友
                        acceptInvitation(presence.getFrom(), true);
                    } catch (Exception exception) {
                        EIMLog.e(_TAG, "" + exception.getMessage());
                    }
                    return;
                }
                Intent intent = new Intent(EIMConstants._USER_INVITE_EVENT_BROADCAST);
                intent.putExtra("username", account);
                intent.putExtra("reason", strStatus);
                intent.putExtra("isResponse", status);
                this.context.sendOrderedBroadcast(intent, null);
                // 对方请求加为好友
                this.userListener.onUserInvited(account, reason);
            }
        } else if (presence.getType().equals(Presence.Type.unsubscribe)) {
            // 删除好友
            EIMUserManager.getInstance().deletedUserAccount.add(presence.getFrom());
            Presence unsubscribe = new Presence(Presence.Type.unsubscribed);
            unsubscribe.setMode(Presence.Mode.available);
            unsubscribe.setPriority(24);
            unsubscribe.setTo(presence.getFrom());
            this.xmppConnectionManager.getConnection().sendPacket(unsubscribe);
        } else if ((presence.getType().equals(Presence.Type.subscribed))) {
            // 对方同意加为好友
            if (status) {
                Intent intent = new Intent(EIMConstants._USER_INVITE_EVENT_BROADCAST);
                intent.putExtra("username", account);
                intent.putExtra("isResponse", status);
                this.context.sendBroadcast(intent);
                this.userListener.onUserAgreed(account);
            }
        }
    }
    
    /**
     * 处理离线好友申请
     */
    public void processOfflinePresences() {
        for (Presence presence : lstOfflineRosterPresence) {
            this.processRosterPresence(presence);
        }
        this.lstOfflineRosterPresence.clear();
    }
}
